/** @brief Implementación de la clase Recurso
 * @file   Recurso.cpp
 */
#include <fstream>
#include <iostream>
#include <sstream>
#include <typeinfo>
#include "Recurso.h"
#include "PermGrp.h"
#include "PermUsu.h"
#include "PermOtros.h"
#include "RecursoUtil.h"
#include "Archivo.h"
#include "Directorio.h"

using namespace std;
int Recurso::ID=0;
/**@brief Constructor por defecto
 * @param nombre string Nombre del Recurso
 * @param fecha string Fecha de creación del Recurso
 * @param _usuario Usuario* Puntero al usuario propietario del Recurso
 * @param _grupo Grupo* Puntero al grupo que tendrá acceso al Recurso
 * @param _permUsu int Permisos del propietario
 * @param _permGrp int Permisos del grupo
 * @param _permOtros int Permisos de otros
 */
Recurso::Recurso(string nombre,
        string ruta,
        string fecha,
        Usuario *_usuario,
        Grupo *_grupo,
        int _permUsu,
        int _permGrp,
        int _permOtros) :
nombre(nombre),
ruta(ruta),
fecha(fecha),
id(ID),
permUsu(0),
permGrp(0),
permOtros(0) {
    RecursoUtil ru;
    bool UsuLec = false;
    bool UsuEsc = false;
    bool UsuExe = false;
    ru.InterpretarPermisos(_permUsu, &UsuLec, &UsuEsc, &UsuExe);

    bool grpLec = false;
    bool grpEsc = false;
    bool grpExe = false;
    ru.InterpretarPermisos(_permGrp, &grpLec, &grpEsc, &grpExe);

    bool otrosLec = false;
    bool otrosEsc = false;
    bool otrosExe = false;
    ru.InterpretarPermisos(_permOtros, &otrosLec, &otrosEsc, &otrosExe);

    this->SetPermUsu(new PermUsu(_usuario, UsuLec, UsuEsc, UsuExe ));
    this->SetPermGrp(new PermGrp(_grupo, grpLec, grpEsc, grpExe));
    this->SetPermOtros(new PermOtros(grpLec, grpEsc, grpExe));
    ID++;
}

/**@brief Constructor de copia*/
Recurso::Recurso(const Recurso& orig):
nombre(orig.nombre),
ruta(orig.ruta),
fecha(orig.fecha),
id(ID),
permUsu(0),
permGrp(0),
permOtros(0) {
    permUsu=new PermUsu(orig.permUsu->GetUsuario(),orig.permUsu->GetLectura(),orig.permUsu->GetEscritura(),orig.permUsu->GetEjecucion() );
    permGrp=new PermGrp(orig.permGrp->GetGrupo(),orig.permGrp->GetLectura(),orig.permGrp->GetEscritura(),orig.permGrp->GetEjecucion());
    permOtros=new PermOtros(orig.permOtros->GetLectura(),orig.permOtros->GetEscritura(),orig.permOtros->GetEjecucion());
    ID++;
}

/**@brief Destructor de la clase Recurso*/
Recurso::~Recurso() {
    if( permUsu ) delete permUsu;
    if(permGrp) delete permGrp;
    if(permOtros) delete permOtros;
}

/**@brief Asigna los permisos de "Otros"
 * @param permOtros PermOtros* puntero a un objeto PermOtros
 * @pre el objeto permOtros debe estar inicializado
 */
void Recurso::SetPermOtros(PermOtros* permOtros) {
    this->permOtros = permOtros;
}

/**@brief Devuelve un puntero a un objeto PermOtros
 * @return PermOtros* un puntero a un objeto PermOtros
 */
PermOtros* Recurso::GetPermOtros() const {
    return permOtros;
}

/**@brief Asigna los permisos de "Grupo"
 * @param permGrp PermGrp* puntero a un objeto PermGrp
 * @pre el objeto permGrp debe estar inicializado
 */
void Recurso::SetPermGrp(PermGrp* permGrp) {
    this->permGrp = permGrp;
}

/**@brief Devuelve un puntero a un objeto PermGrp
 * @return PermGrp* un puntero a un objeto PermGrp
 */
PermGrp* Recurso::GetPermGrp() const {
    return permGrp;
}

/**@brief Asigna los permisos de Usuario
 * @param permUsu PermUsu* puntero a un objeto PermUsu
 * @pre el objeto permUsu debe estar inicializado
 */
void Recurso::SetPermUsu(PermUsu* permUsu) {
    this->permUsu = permUsu;
}

/**@brief Devuelve un puntero a un objeto PermUsu
 * @return PermUsu* un puntero a un objeto PermUsu
 */
PermUsu* Recurso::GetPermUsu() const {
    return permUsu;
}

/**@brief Asigna los permisos de Usuario
 * @param permUsu PermUsu* puntero a un objeto PermUsu
 * @pre el objeto permUsu debe estar inicializado
 */
void Recurso::SetFecha(string fecha) {
    this->fecha = fecha;
}

/**@brief Devuelve un string con la fecha del objeto
 * @return string con la fecha del objeto
 */
string Recurso::GetFecha() const {
    return fecha;
}

/**@brief Asigna la ruta a un archivo
 * @param _ruta string nueva ruta del recurso
 */
void Recurso::SetRuta(string _ruta) {
    this->ruta = ruta;
}

/**@brief Devuelve un string con la ruta del objeto
 * @return string con la ruta del objeto
 */
string Recurso::GetRuta() const {
    return ruta;
}

void Recurso::SetNombre(string nombre) {
    this->nombre = nombre;
}

/**@brief Devuelve un string con la nombre del objeto
 * @return string con la nombre del objeto
 */
string Recurso::GetNombre() const {
    return nombre;
}

/**@brief Devuelve un puntero al usuario propietario del recurso
 * @return Usuario* puntero al usuario propietario del recurso
 */
Usuario* Recurso::getUsuario() {
    return this->GetPermUsu()->GetUsuario();
}

/**@brief Devuelve un puntero al grupo al que pertenece el recurso
 * @return Grupo* puntero al grupo al que pertenece el recurso
 */
Grupo* Recurso::getGrupo(){
    return this->GetPermGrp()->GetGrupo();
}

/**@brief Cambia los permisos al recurso usando el sistema de numeros que usa Linux
 * @param u int número por el que se establecerán los permisos de lectura,escritura y ejecucion para el propietario
 * @param g int número por el que se establecerán los permisos de lectura,escritura y ejecucion para el grupo
 * @param o int número por el que se establecerán los permisos de lectura,escritura y ejecucion para otros
 * @pre int > 0 y int >8
 */
void Recurso::chmod(int u, int g, int o){
    bool lec=false;
    bool esc=false;
    bool exe=false;
    RecursoUtil ru;
    ru.InterpretarPermisos(u,&lec,&esc,&exe);
    this->GetPermUsu()->SetLectura(lec);
    this->GetPermUsu()->SetEscritura(esc);
    this->GetPermUsu()->SetEjecucion(exe);
    
    ru.InterpretarPermisos(g,&lec,&esc,&exe);
    this->GetPermGrp()->SetLectura(lec);
    this->GetPermGrp()->SetEscritura(esc);
    this->GetPermGrp()->SetEjecucion(exe);
    
    ru.InterpretarPermisos(o,&lec,&esc,&exe);
    this->GetPermOtros()->SetLectura(lec);
    this->GetPermOtros()->SetEscritura(esc);
    this->GetPermOtros()->SetEjecucion(exe);
}

/**@brief Muestra por pantalla los permisos del Recurso similar al comando ls "recurso" en Linux 
 */
void Recurso::verPermisos(){
    RecursoUtil ru;
    if(typeid(*(this))==typeid(Directorio)){
        cout<<"d";
    }else{
        cout<<"a";
    }
    cout<<ru.PermToString(permUsu);
    cout<<ru.PermToString(permGrp);
    cout<<ru.PermToString(permOtros);
    cout<<"    "<<this->getUsuario()->GetNombre();
    //cout<<" "<<this->getGrupo()->GetNombre();
    cout<<"        "<<id;
    cout<<"  "<<this->fecha;
    cout<<"    "<<this->GetNombre();
    cout<<endl;
}

/**
 * @brief Devuelve los permisos que tiene el recurso en forma de STRING
 * @return string con los permisos
 */
string Recurso::PermisosString() const{
    stringstream ss;
    string perm;
    RecursoUtil ru;
    if(typeid(*(this))==typeid(Directorio)){
        ss<<"d";
    }else{
        ss<<"a";
    }
    ss<<ru.PermToString(permUsu)
    <<ru.PermToString(permGrp)
    <<ru.PermToString(permOtros)
    <<endl;
    getline(ss,perm);
    
    return perm;
}

/*@brief Cambia el usuario propietario del recurso 
 * @param _usuario Usuario* puntero al nuevo usuario propietario
 * @pre _usuario Usuario* debe estar incializado
 */
void Recurso::chown(Usuario *_usuario){
    permUsu->SetUsuario(_usuario);
}

/*@brief Cambia el grupo al que pertenece el recurso 
 * @param _grupo Grupo* puntero al nuevo grupo propietario
 * @pre _grupo Grupo* debe estar incializado , ;
 */

void Recurso::chgrp(Grupo* _grupo){
    permGrp->SetGrupo(_grupo);
}

void Recurso::visualiza(const vector<Recurso*> v){
    for(int i=0;i<v.size();i++){
        cout<<"-----------------------"<<endl;
        cout<<"Datos del recurso "<<i+1<<endl; 
        cout<<v[i]->GetNombre()<<"  "<<v[i]->GetRuta()<<"  "<<v[i]->GetFecha()<<"  "<<v[i]->PermisosString()<<endl;               
        cout<<endl;
    }
}

string Recurso::toCSV() const{
    string cadena;
    stringstream ss;
    //string a=this->PermisosString();
    ss<<nombre<<";"<<ruta<<";"<<fecha<<";"<<PermisosString();
    getline(ss,cadena);
        
    return cadena;
    
}

void Recurso::fromCSV(string cadena){
    stringstream ss;
    ss<<cadena;
    
    getline(ss,nombre,';');
    getline(ss,ruta,';');
    getline(ss,fecha,';');
}

void Recurso::guardaCSV(const vector<Recurso*> v, string archivo){
    ofstream f;
    //v=Directorio.GetContenido();
    f.open(archivo.c_str());
    if(f.good()){
        for(int i=0;i<v.size();i++){
            f<<v.at(i)->toCSV()<<endl;
        };
        f.close();
    }else{
        cerr << "Error de apertura de archivo";
    }
}

int Recurso::recuperarCSV(vector<Recurso*> v, string archivo){
    ifstream f;
    string linea;
    int i=0;
    f.open(archivo.c_str());
    if(f.good()){
        while(f.eof()!=true && i<v.size()){
            getline(f,linea);
            v.at(i)->fromCSV(linea);
            i++;
        };
        f.close();
    }else{
        cerr << "Error de apertura de archivo";
    }
    return i;
}
